package com.ilikesoup.instant.empty;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * 空判断工具类
 * <p>
 * 此处的空表示：null/空串/没有元素的集合或数组/自定义空
 *
 * 批量重构：
 * (Regex模式查找替换)
 * Search: (\w+(?:\.\w+\(\))+) == null \|\| (\w+(?:\.\w+\(\))+)(\.trim\(\))?\.isEmpty\(\)
 * Replace: EmptyUtils.isEmpty($1)
 *
 * @author soup
 * @date 2018年5月18日 上午11:21:55
 * @see Emptiable
 */
public class EmptyUtils {

    private EmptyUtils() {
        throw new RuntimeException("Must not be instantiated!");
    }

    /**
     * 判断一个对象是否为空，并且根据它的类型来判断它是否是空的
     *
     * @param o
     * @return
     */
    public static boolean isEmpty(Object o) {
        if (o == null) {
            return true;
        }
        if (o instanceof String) {
            return isEmpty0((String) o, true);
        } else if (o instanceof Collection<?>) {
            return ((Collection<?>) o).isEmpty();
        } else if (o instanceof Map<?, ?>) {
            return ((Map<?, ?>) o).isEmpty();
        } else if (o instanceof Emptiable) {
            return ((Emptiable) o).isEmpty();
        } else if (o.getClass().isArray()) {
            return Array.getLength(o) == 0;
        }
        return false;
    }

    public static boolean isNotEmpty(Object o) {
        return !isEmpty(o);
    }


    /**
     * 字符串判空，默认trim
     *
     * @param str
     * @return
     */
    public static boolean isEmpty(String str) {
        return isEmpty(str, true);
    }
    public static boolean isNotEmpty(String o) {
        return !isEmpty(o);
    }
    /**
     * 字符串判空，有trim选项
     *
     * @param str
     * @param trim
     * @return
     */
    public static boolean isEmpty(String str, boolean trim) {
        if (str == null) {
            return true;
        }
        return isEmpty0(str, trim);
    }

    private static boolean isEmpty0(String str, boolean trim) {
        if (trim) {
            int strLen = str.length();
            for (int i = 0; i < strLen; i++) {
                if (!Character.isWhitespace(str.charAt(i))) {
                    return false;
                }
            }
            return true;
        } else {
            return str.length() == 0;
        }
    }

    /**
     * 数组判空
     *
     * @param array
     * @return
     */
    public static boolean isEmpty(Object[] array) {
        return array == null || array.length == 0;
    }
    public static boolean isEmpty(byte[] array) {
        return array == null || array.length == 0;
    }
    public static boolean isEmpty(short[] array) {
        return array == null || array.length == 0;
    }
    public static boolean isEmpty(int[] array) {
        return array == null || array.length == 0;
    }
    public static boolean isEmpty(long[] array) {
        return array == null || array.length == 0;
    }
    public static boolean isEmpty(float[] array) {
        return array == null || array.length == 0;
    }
    public static boolean isEmpty(double[] array) {
        return array == null || array.length == 0;
    }
    public static boolean isEmpty(boolean[] array) {
        return array == null || array.length == 0;
    }
    public static boolean isEmpty(char[] array) {
        return array == null || array.length == 0;
    }

    public static boolean isNotEmpty(Object[] array) {
        return !isEmpty(array);
    }
    public static boolean isNotEmpty(byte[] array) {
        return !isEmpty(array);
    }
    public static boolean isNotEmpty(short[] array) {
        return !isEmpty(array);
    }
    public static boolean isNotEmpty(int[] array) {
        return !isEmpty(array);
    }
    public static boolean isNotEmpty(long[] array) {
        return !isEmpty(array);
    }
    public static boolean isNotEmpty(float[] array) {
        return !isEmpty(array);
    }
    public static boolean isNotEmpty(double[] array) {
        return !isEmpty(array);
    }
    public static boolean isNotEmpty(boolean[] array) {
        return !isEmpty(array);
    }
    public static boolean isNotEmpty(char[] array) {
        return !isEmpty(array);
    }
    /**
     * 集合判空
     *
     * @param coll
     * @return
     */
    public static boolean isEmpty(Collection<?> coll) {
        return isEmpty(coll, Collection::isEmpty);
    }
    public static boolean isNotEmpty(Collection<?> o) {
        return !isEmpty(o);
    }

    /**
     * map判空
     *
     * @param map
     * @return
     */
    public static boolean isEmpty(Map<?, ?> map) {
        return map == null || map.isEmpty();
    }
    public static boolean isNotEmpty(Map<?, ?> o) {
        return !isEmpty(o);
    }

    /**
     * 实现可空接口对象判空
     *
     * @param obj
     * @return
     */
    public static boolean isEmpty(Emptiable obj) {
        return isEmpty(obj, Emptiable::isEmpty);
    }
    public static boolean isNotEmpty(Emptiable o) {
        return !isEmpty(o);
    }

    public static <T> boolean isEmpty(T obj, Predicate<T> emptyPredicate) {
        return obj == null || emptyPredicate.test(obj);
    }

    public static <T> Predicate<T> predicate(Function<T, ?> mapping) {
        return obj -> EmptyUtils.isEmpty(mapping.apply(obj));
    }

}

